home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / ctask.zip / TSKSUB.C < prev    next >
C/C++ Source or Header  |  1988-07-01  |  6KB  |  301 lines

  1. /*
  2.    CTask Subroutines
  3.  
  4.    Public Domain Software written by
  5.       Thomas Wagner
  6.       Patschkauer Weg 31
  7.       D-1000 Berlin 33
  8.       West Germany
  9.  
  10.    Version 1.1  88-07-01
  11.  
  12.       Changes from V0.1: - Handling of timeout queue rewritten
  13.                          - Timeouts in milliseconds (optional)
  14.                          - Support for dynamically allocated control blocks.
  15. */
  16.  
  17. #include <stdio.h>
  18.  
  19. #include "tsk.h"
  20. #include "tsklocal.h"
  21.  
  22. /*
  23.    tsk_enqueue  inserts a task into a queue based on priority.
  24. */
  25.  
  26. void far tsk_enqueue (tcbptr task, tqueptr que)
  27. {
  28.    tcbptr last, curr;
  29.  
  30.    last = NULL;
  31.    curr = *que;
  32.  
  33.    while (curr != NULL && curr->prior >= task->prior)
  34.       {
  35.       last = curr;
  36.       curr = curr->next;
  37.       }
  38.    task->next = curr;
  39.    if (last == NULL)
  40.       *que = task;
  41.    else
  42.       last->next = task;
  43.    task->queue = que;
  44. }
  45.  
  46.  
  47. /*
  48.    tsk_unqueue 
  49.       Removes a task from somewhere in the middle of a queue. It is only
  50.       used when stopping or prematurely waking a task, since in all other 
  51.       circumstances a task is only removed from the head of a queue.
  52. */
  53.  
  54. void far tsk_unqueue (tcbptr task)
  55. {
  56.    tcbptr last, curr;
  57.  
  58.    if (task->state == ST_RUNNING || task->queue == NULL)
  59.       return;
  60.  
  61.    last = NULL;
  62.    curr = *task->queue;
  63.  
  64.    while (curr != task)
  65.       {
  66.       if (curr == NULL)
  67.          return;
  68.       last = curr;
  69.       curr = curr->next;
  70.       }
  71.    if (last == NULL)
  72.       *task->queue = curr->next;
  73.    else
  74.       last->next = curr->next;
  75.    task->queue = NULL;
  76. }
  77.  
  78.  
  79. /*
  80.    tsk_enqtimer inserts a task into the timer queue.
  81. */
  82.  
  83. void far tsk_enqtimer (tcbptr task, dword tout)
  84. {
  85.    tlinkptr curr;
  86.  
  87.    if (tout == 0)
  88.       return;
  89.  
  90.    /*
  91.       Tasks are not sorted in the timer queue, so the task is inserted
  92.       at the queue head. The timer task has to step through all tasks
  93.       in the queue to cont down the timeout, so sorting would not bring
  94.       any advantages.
  95.    */
  96.  
  97.    curr = &task->timerq;
  98.    curr->timeout = tsk_timeout(tout);
  99.    if (curr->tstate == TSTAT_IDLE)
  100.       {
  101.       curr->next = tsk_timer;
  102.       tsk_timer = curr;
  103.       }
  104.    curr->tstate = TSTAT_COUNTDOWN;
  105. }
  106.  
  107.  
  108. /*
  109.    tsk_runable
  110.       make a task eligible for running. The task is removed from the
  111.       timer queue and enqueued in the eligible queue. The old "next"
  112.       pointer of the tcb is returned. This assumes that the task
  113.       is removed from the head of a queue.
  114. */
  115.  
  116. tcbptr far tsk_runable (tcbptr task)
  117. {
  118.    tcbptr nxt;
  119.  
  120.    nxt = task->next;
  121.    task->state = ST_ELIGIBLE;
  122.    tsk_unqtimer (task);
  123.    tsk_enqueue (task, &tsk_eligible);
  124.    return nxt;
  125. }
  126.  
  127.  
  128. /*
  129.    tsk_wakeup
  130.       make a task eligible for running. The task is removed from the
  131.       timer queue and enqueued in the eligible queue. 
  132.       This routine assumes that the task is removed from the middle of
  133.       a queue.
  134. */
  135.  
  136. void far tsk_wakeup (tcbptr task)
  137. {
  138.    task->state = ST_ELIGIBLE;
  139.    tsk_unqueue (task);
  140.    tsk_unqtimer (task);
  141.    tsk_enqueue (task, &tsk_eligible);
  142. }
  143.  
  144.  
  145. /*
  146.    tsk_wait - put current running task in wait state.
  147.               Note that the task is NOT enqueued in the respective queue
  148.               here, this is done by the scheduler based on the queue head
  149.               pointer. Only the timeout queue is affected directly.
  150. */
  151.  
  152. void far tsk_wait (tqueptr que, dword timeout)
  153. {
  154.    tsk_current->state = ST_WAITING;
  155.    tsk_current->queue = que;
  156.    tsk_enqtimer (tsk_current, timeout);
  157.    schedule ();
  158. }
  159.  
  160.  
  161. /*
  162.    tsk_kill - mark task as killed.
  163. */
  164.  
  165. void far tsk_kill (tcbptr task)
  166. {
  167. #if (TSK_NAMED)
  168.    tsk_del_name (&task->name);
  169. #endif
  170.  
  171.    task->state = ST_KILLED;
  172.    if (task->timerq.tstate != TSTAT_IDLE)
  173.       {
  174.       task->timerq.tstate = (byte) TSTAT_REMOVE;
  175. #if (TSK_DYNAMIC)
  176.       if (task->flags & F_TEMP)
  177.          task->timerq.tkind |= TKIND_TEMP;
  178.       }
  179.    else 
  180.       {
  181.       if (task->flags & F_STTEMP)
  182.          tsk_free (task->stack);
  183.       if (task->flags & F_TEMP)
  184.          tsk_free (task);
  185.       }
  186. #else
  187.       }
  188. #endif
  189. }
  190.  
  191. /*
  192.    tsk_kill_queue
  193.       Removes all tasks from a queue. For internal use only, critical
  194.       section assumed entered.
  195. */
  196.  
  197. void far tsk_kill_queue (tqueptr que)
  198. {
  199.    tcbptr curr;
  200.  
  201.    for (curr = *que; curr != NULL; curr = curr->next)
  202.       {
  203.       tsk_unqtimer (curr);
  204.       tsk_kill (curr);
  205.       }
  206.    *que = NULL;
  207. }
  208.  
  209.  
  210. #if (CLOCK_MSEC)
  211.  
  212. dword tsk_timeout (dword tout)
  213. {
  214.    dword t;
  215.  
  216.    t = (dword) (((double)tout / tick_factor) + 0.5);
  217.    return (t) ? t : 1; 
  218. }
  219.  
  220. #endif
  221.  
  222. #if (TSK_NAMED)
  223.  
  224. /*
  225.    tsk_add_name
  226.       Initialise name-list element and insert it at the end of the list.
  227.       NOTE: no check is made for duplicate names; names are not sorted.
  228. */
  229.  
  230. void far tsk_add_name (nameptr elem, byteptr name, byte kind, farptr strucp)
  231. {
  232.    byteptr n;
  233.    int i;
  234.    CRITICAL;
  235.  
  236.    elem->nkind = kind;
  237.    elem->strucp = strucp;
  238.    n = elem->name;
  239.    if (name != NULL)
  240.       for (i = 0; i < 8; i++)
  241.          if (!(*n++ = *name++))
  242.             break;
  243.    *n = 0;
  244.  
  245.    C_ENTER;
  246.    elem->prev = tsk_name_list.prev;
  247.    tsk_name_list.prev = elem;
  248.    elem->follow = &tsk_name_list;
  249.    elem->prev->follow = elem;
  250.    C_LEAVE;
  251. }
  252.  
  253.  
  254. /*
  255.    tsk_del_name
  256.       delete name-element from the name-list.
  257. */
  258.  
  259. void far tsk_del_name (nameptr elem)
  260. {
  261.    CRITICAL;
  262.  
  263.    C_ENTER;
  264.    elem->follow->prev = elem->prev;
  265.    elem->prev->follow = elem->follow;
  266.    C_LEAVE;
  267. }
  268.  
  269.  
  270. /*
  271.    find_name
  272.       find structure, given name and type. 
  273.       If type is zero, the first name-element matching the name is returned.
  274.       If type is nonzero, the first structure matching the name and type is
  275.       returned.
  276. */
  277.  
  278. local int tsk_streq (byteptr n1, byteptr n2)
  279. {
  280.    while (*n1 && *n1 == *n2)
  281.       {
  282.       n1++;
  283.       n2++;
  284.       }
  285.    return *n1 == *n2; 
  286. }
  287.  
  288. farptr far find_name (byteptr name, byte kind)
  289. {
  290.    nameptr curr;
  291.  
  292.    for (curr = tsk_name_list.follow; curr->nkind; curr = curr->follow)
  293.       if (!kind || curr->nkind == kind)
  294.          if (tsk_streq (name, curr->name))
  295.             return (kind) ? curr->strucp : curr;
  296.  
  297.    return NULL;
  298. }
  299. #endif
  300.  
  301.